/*
 * @Author       : wfl
 * @LastEditors  : wfl
 * @description  :
 * @updateInfo   :
 * @Date         : 2023-11-07 19:28:12
 * @LastEditTime : 2024-01-29 17:28:44
 */
import { Config } from '@midwayjs/decorator';
import { Context } from 'vm';
import { Post, Provide, Body, Get, Query } from '@midwayjs/decorator';
import { CoolController, BaseController, RESCODE } from '@cool-midway/core';
import { ScreenDataBaseEntity } from '../../entity/base';
import { ScreenDataBaseService } from '../../service/base';
import { DataSource } from 'typeorm';
/**
 * 数据库-基本信息
 */
@Provide()
@CoolController({
  api: [],
  entity: ScreenDataBaseEntity,
  service: ScreenDataBaseService,
})
export class DatabaseController extends BaseController {
  async createConnect(body) {
    const dataSource = new DataSource(body);
    await dataSource.initialize();

    return {
      dataSource,
      destroy: function () {
        dataSource.destroy();
      },
    };
  }

  @Post('/test/connection')
  async testConnect(@Body() body) {
    const { dataSource, destroy } = await this.createConnect(body);
    const connectioning = dataSource.isConnected;
    destroy();
    return connectioning ? this.ok() : this.fail();
  }

  @Post('/execute/sql')
  async executeSQL(
    @Body() body: { base: string; sql: string; table?: string }
  ) {
    try {
      if (!body.sql?.toLocaleLowerCase().startsWith('select')) {
        return this.fail(
          '不允许的SQL,仅允许SELECT语句,请修改后重试',
          RESCODE.SUCCESS
        );
      }
      if (
        body.sql?.toLocaleLowerCase().includes('insert') ||
        body.sql?.toLocaleLowerCase().includes('delete') ||
        body.sql?.toLocaleLowerCase().includes('update')
      ) {
        return this.fail(
          '不允许的SQL,仅允许SELECT语句,请修改后重试',
          RESCODE.SUCCESS
        );
      }
      const DB = await (this.service as any).queryBasesId(body.base);
      const con: any = {
        type: DB.type,
        host: DB.host,
        port: DB.port,
        username: DB.username,
        password: DB.password,
      };
      if (body.table) {
        con.database = body.table;
      }
      const { dataSource, destroy } = await this.createConnect(con);
      const res = await dataSource.query(body.sql);
      destroy();
      return res;
    } catch (error) {
      console.error('error: ', error);
      return this.fail();
    }
  }

  @Get('/bases')
  async queryBasess(@Query('id') id) {
    try {
      const DB = await (this.service as any).queryBasesId(id);
      const { dataSource, destroy } = await this.createConnect(DB);
      const dbs = await dataSource.query('SHOW DATABASES;');
      const data = dbs.map(d => ({ value: d.Database }));
      return this.ok(data);
    } catch (error) {
      return this.fail();
    }
  }
  @Post('/tables')
  async queryTables(@Body() body) {
    try {
      const DB = await (this.service as any).queryBasesId(body.id);
      const { dataSource, destroy } = await this.createConnect(DB);
      const tables = await dataSource.query(
        `SELECT table_name FROM information_schema.tables WHERE table_schema = '${body.base}';`
      );
      const reTables = tables.map(ta => ta.TABLE_NAME);
      destroy();
      return this.ok(reTables);
    } catch (error) {
      return this.fail();
    }
  }
  @Post('/table/keys')
  async queryTableByKeys(@Body() body) {
    try {
      const DB = await (this.service as any).queryBasesId(body.id);
      const { dataSource, destroy } = await this.createConnect(DB);
      const tableKeys = await dataSource.query(`SELECT COLUMN_NAME, DATA_TYPE
                FROM INFORMATION_SCHEMA.COLUMNS
                WHERE TABLE_SCHEMA = '${body.base}' AND TABLE_NAME = '${body.key}';`);
      const reTables = tableKeys.map(v => {
        return {
          ...v,
          value: v.COLUMN_NAME,
        };
      });
      destroy();
      return this.ok(reTables);
    } catch (error) {
      return this.fail();
    }
  }
}
